home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Add-On
/
Workbench Add-On - Volume 1.iso
/
BBS-Archive
/
Comm
/
AmiTCP30b2.lha
/
src
/
amitcp
/
kern
/
amiga_netdb.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-06
|
25KB
|
1,006 lines
RCS_ID_C="$Id: amiga_netdb.c,v 3.2 1994/04/06 15:37:29 too Exp $";
/*
* amiga_netdb.c --- NetDB Parse Functions
*
* Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
* Helsinki University of Technology, Finland.
* All rights reserved.
*
* Created : Tue Apr 27 10:18:58 1993 ppessi
* Last modified: Wed Apr 6 18:14:49 1994 too
*
* $Log: amiga_netdb.c,v $
* Revision 3.2 1994/04/06 15:37:29 too
* Added parsing of '@' as match for all private ports (# < 1024)
* in addaccessent()
*
* Revision 3.1 1994/03/26 09:41:13 too
* Added netdb parsing code for ACCESS control
*
* Revision 1.14 1993/07/28 16:00:43 jraja
* Fixed two inet_aton() calls (return value was misunderstood).
*
* Revision 1.13 1993/06/14 15:37:48 jraja
* Changed file line handling to somewhat better.
* Added check for too deep recursion of the netdb files.
*
* Revision 1.12 1993/06/13 23:39:27 jraja
* Changed HOST to use Unix compatible format.
* Added WITH to include other files.
* '#' as a comment introducer now fully supported.
* Uses parse function table instead of a switch-case structure.
* read_netdb() now supports 'prefixes'.
* read_netdb() now CD's to the AmiTCP:db before opening the file.
*
* Revision 1.11 1993/06/04 11:16:15 jraja
* Fixes for first public release.
*
* Revision 1.10 1993/05/29 20:54:12 jraja
* Changed to use _PATH_NETDB.
*
* Revision 1.9 1993/05/17 01:07:47 ppessi
* Changed RCS version.
*
* Revision 1.8 1993/05/16 19:24:03 jraja
* Changed structure names:
* NameServerNode => NameserventNode, nameserver => nameservent,
* DomainNode => DomainentNode, domainname => domainent.
*
* Revision 1.7 1993/05/16 00:48:14 jraja
* Changed init_netdb() to forgive file errors.
*
* Revision 1.6 1993/05/16 00:17:32 jraja
* Changed return values from explicit numbers to RETURN_XXXX.
* Changed syntax errors to be logged and bypassed.
* Implemented nameserver and domain parsing.
*
* Revision 1.5 93/05/14 11:37:11 11:37:11 ppessi (Pekka Pessi)
* Cleaned Arexx interface a bit. Private information removed from
* header files, added to this file.
*
* Revision 1.4 93/05/05 16:10:10 16:10:10 puhuri (Markus Peuhkuri)
* Fixes for final demo.
*
* Revision 1.3 93/05/04 16:53:28 16:53:28 ppessi (Pekka Pessi)
* Added net and host entry parsing.
*
* Revision 1.2 93/05/04 12:38:32 12:38:32 jraja (Jarno Tapio Rajahalme)
* _Minor_ fixes...
*
* Revision 1.1 93/04/28 21:56:49 21:56:49 ppessi (Pekka Pessi)
* Initial revision
*
*/
#include <conf.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/syslog.h>
#include <sys/socket.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <kern/amiga_includes.h>
#include <kern/amiga_config.h>
#include <kern/amiga_netdb.h>
#include <kern/accesscontrol.h>
#include <netinet/in.h>
#include <dos/dos.h>
#include <dos/rdargs.h>
#if __SASC
#include <proto/dos.h>
#elif __GNUC__
#include <inline/dos.h>
#else
#error Your compiler is not supported in this release.
#endif
int inet_aton(register const char *cp, struct in_addr *addr);
LONG read_netdb(struct NetDataBase *ndb, UBYTE *fname, const UBYTE** errstrp, struct CSource *res, int prefixindex);
/*
* Global pointer for the NetDataBase
*/
struct NetDataBase *NDB = NULL;
/*
* Default netdatabase name
*/
STRPTR netdbname = _PATH_NETDB;
/*
* Templates for Arexx commands and DB files
*/
STRPTR NETDBENTRY =
"WITH,H=HOST,N=NET,S=SERVICE,P=PROTOCOL,NS=NAMESERVER,DO=DOMAIN,ACC=ACCESS";
enum ndbtype { KNDB_WITH, KNDB_HOST, KNDB_NET, KNDB_SERV, KNDB_PROTO,
KNDB_DNS, KNDB_DOM, KNDB_ACC };
STRPTR NETDBTEMPLATE =
"$NAME$/A,$ENTRY$/A,$ALIAS$/M";
STRPTR PROTOCOL_TEMPLATE =
"$NAME$/A,$NUMBER$/A/N,$ALIAS$/M";
enum ndbarg { KNDB_NAME, KNDB_DATA, KNDB_ALIAS };
#define NDBARGS 3
STRPTR ACCESS_TEMPLATE =
"$PORT$/A,$HOSTMASK$/A,$ACCESS$/A,LOG/S";
enum accarg { KACC_PORT, KACC_HOSTMASK, KACC_ACCESS, KACC_LOG };
#define ACCARGS 4
STRPTR WITH_TEMPLATE =
"$FILE$/A,PREFIX/K";
#define WITHARGS 2
enum witharg { WITH_FILE, WITH_PREFIX };
/* prototypes for the netdb parsing functions */
LONG addwith(struct NetDataBase *ndb,
struct RDArgs *rdargs, UBYTE **errstrp);
LONG addhostent(struct NetDataBase *ndb,
struct RDArgs *rdargs, UBYTE **errstrp);
LONG addnetent(struct NetDataBase *ndb,
struct RDArgs *rdargs, UBYTE **errstrp);
LONG addservent(struct NetDataBase *ndb,
struct RDArgs *rdargs, UBYTE **errstrp);
LONG addprotoent(struct NetDataBase *ndb,
struct RDArgs *rdargs, UBYTE **errstrp);
LONG addnameservent(struct NetDataBase *ndb,
struct RDArgs *rdargs, UBYTE **errstrp);
LONG adddomainent(struct NetDataBase *ndb,
struct RDArgs *rdargs, UBYTE **errstrp);
LONG addaccessent(struct NetDataBase *ndb,
struct RDArgs *rdargs, const UBYTE **errstrp);
LONG addndbent(struct NetDataBase *ndb,
struct RDArgs *rdargs, UBYTE **errstrp);
typedef LONG (*ndb_parse_f)(struct NetDataBase *ndb,
struct RDArgs *rdargs, UBYTE **errstrp);
/* Array of parsing functions. Note that the order is same as in the
* NETDBENTRY.
*/
ndb_parse_f ndb_parse_funs[] = {
addwith,
addhostent,
addnetent,
addservent,
addprotoent,
addnameservent,
adddomainent,
addaccessent
};
/*
* Alloc a NetDataBase
*/
struct NetDataBase *
alloc_netdb(struct NetDataBase *ndb)
{
if (ndb ||
(ndb = bsd_malloc(sizeof (*NDB), M_NETDB, M_WAITOK))) {
struct MinList *gl;
InitSemaphore(&ndb->ndb_Lock);
for (gl = (struct MinList *)&ndb->ndb_Hosts;
gl <= (struct MinList *)&ndb->ndb_Domains;
gl++)
NewList((struct List *)gl);
}
ndb->ndb_AccessCount = 0;
if ((ndb->ndb_AccessTable =
bsd_malloc(TMPACTSIZE, M_NETDB, M_WAITOK)) == NULL) {
bsd_free(ndb, M_NETDB);
ndb = NULL;
}
return ndb;
}
/*
* Free a NetDataBase
* Caller must have a write lock on NDB
*/
void
free_netdb(struct NetDataBase *ndb)
{
struct GenentNode *gn;
struct MinList *gl;
for (gl = (struct MinList *)&ndb->ndb_Hosts;
gl <= (struct MinList *)&ndb->ndb_Domains;
gl++)
while (gn = (struct GenentNode *)RemHead((struct List *)gl))
bsd_free(gn, M_NETDB);
if (ndb->ndb_AccessTable != NULL) {
bsd_free(ndb->ndb_AccessTable, M_NETDB);
ndb->ndb_AccessTable = NULL;
}
bsd_free(ndb, M_NETDB);
}
#ifdef DEBUG
static char * zap;
static size_t zap_size;
#endif
/*
* Copy alias list to ato, alias strings and name to cto
*/
static void
aliascpy(UBYTE *cto, UBYTE *name, UBYTE**ato, UBYTE **afrom)
{
#ifdef DEBUG
UBYTE *logname = name;
#endif
do {
while(*cto++ = *name++);
} while (afrom && (name = *afrom++) && (*ato++ = cto));
*ato = NULL;
#ifdef DEBUG
if (cto != zap + zap_size) {
log(LOG_ERR, "%s: mismatch in size %ld != expected %ld\n",
logname, cto - zap, zap_size);
}
#endif
}
/*
* Allocate a netdb node
*
* nodesize is the size of the base structure, additional space
* is allocated for the name and the aliases.
* alias is NULL terminated array of alias name pointers.
* Number of aliases is returned via aliasp.
*
* size field of the allocated node is set to the total size - size for
* the MinNode and the size field itself.
*/
static void *
node_alloc(size_t nodesize, UBYTE *name, UBYTE **alias, int *aliasp)
{
struct GenentNode *gn;
nodesize += strlen(name) + 1; /* Add space needed for the name */
*aliasp = 1;
nodesize += sizeof (char*); /* Alias list NULL terminator */
/* Calculate the size of the aliases */
if (alias) {
while (*alias) {
(*aliasp)++;
nodesize += strlen(*alias++) + 1 + sizeof (char*);
}
}
gn = bsd_malloc(nodesize, M_NETDB, M_WAITOK);
/*
* set the ent size
*/
if (gn)
gn->gn_EntSize = nodesize - sizeof (struct GenentNode);
#ifdef DEBUG
zap_size = nodesize;
zap = (char *)gn;
#endif
return gn;
}
/*
* Parse a service entry.
*/
LONG
addwith(struct NetDataBase *ndb,
struct RDArgs *rdargs,
UBYTE **errstrp)
{
UBYTE result[REPLYBUFLEN + 1];
struct CSource res;
LONG retval = RETURN_OK;
LONG Args[WITHARGS] = { 0 };
int which;
res.CS_Buffer = result;
res.CS_Length = sizeof (result);
res.CS_CurChr = 0;
if (rdargs = ReadArgs(WITH_TEMPLATE, Args, rdargs)) {
if (Args[WITH_PREFIX] == 0) /* no prefix given */
which = -1;
else {
/* match given prefix */
which = FindArg(NETDBENTRY, (UBYTE *)Args[WITH_PREFIX]);
if (which < 0) {
*errstrp = ERR_VALUE;
retval = RETURN_WARN;
}
}
if (retval == RETURN_OK) {
retval = read_netdb(ndb, (UBYTE *)Args[WITH_FILE], errstrp, &res,
which);
if (retval) {
log(LOG_WARNING, "netdb: WITH file %s: %s",
(UBYTE *)Args[WITH_FILE], *errstrp);
#if 0
if (retval <= RETURN_ERROR)
retval = RETURN_OK; /* forgive */
#endif
}
}
FreeArgs(rdargs);
} else {
*errstrp = ERR_SYNTAX; retval = RETURN_WARN;
}
return retval;
}
/*
* Parse a service entry.
*/
LONG
addservent(struct NetDataBase *ndb,
struct RDArgs *rdargs,
UBYTE **errstrp)
{
LONG retval;
LONG Args[NDBARGS] = { 0 };
struct ServentNode *sn;
int aliases, plen;
if (rdargs = ReadArgs(NETDBTEMPLATE, Args, rdargs)) {
/* convert port number */
UBYTE *s_proto = (UBYTE*)Args[KNDB_DATA];
if ((plen = StrToLong(s_proto, &Args[KNDB_DATA])) > 0 &&
s_proto[plen++] == '/') {
int protonamelen = strlen(s_proto = s_proto + plen) + 1;
sn = node_alloc(sizeof (*sn) + protonamelen,
(UBYTE*)Args[KNDB_NAME],
(UBYTE **)Args[KNDB_ALIAS], &aliases);
if (sn) {
UBYTE **alias = (UBYTE **)(sn+1);
UBYTE *name = (UBYTE *)(alias + aliases);
sn->sn_Ent.s_port = Args[KNDB_DATA];
sn->sn_Ent.s_proto = strcpy(name, s_proto);
sn->sn_Ent.s_name = name + protonamelen;
sn->sn_Ent.s_aliases = (char **)alias;
/* Copy aliases */
aliascpy(sn->sn_Ent.s_name, (UBYTE*)Args[KNDB_NAME],
alias, (UBYTE **)Args[KNDB_ALIAS]);
AddTail((struct List*)&ndb->ndb_Services, (struct Node*)sn);
retval = RETURN_OK;
} else {
*errstrp = ERR_MEMORY; retval = RETURN_FAIL;
}
} else {
*errstrp = ERR_VALUE; retval = RETURN_WARN;
}
FreeArgs(rdargs);
} else {
*errstrp = ERR_SYNTAX; retval = RETURN_WARN;
}
return retval;
}
/*
* Parse a host entry.
*
* NOTE: The host entry has the address in the 'name' and the official name
* in the 'data'.
*/
LONG
addhostent(struct NetDataBase *ndb,
struct RDArgs *rdargs,
UBYTE **errstrp)
{
LONG retval;
LONG Args[NDBARGS] = { 0 };
struct HostentNode *hn;
struct in_addr addr;
int aliases;
if (rdargs = ReadArgs(NETDBTEMPLATE, Args, rdargs)) {
/* convert ip address */
if (inet_aton((char*)Args[KNDB_NAME], &addr)) {
hn = node_alloc(sizeof (*hn) + 2*sizeof (&addr) + sizeof (addr),
(UBYTE*)Args[KNDB_DATA],
(UBYTE **)Args[KNDB_ALIAS], &aliases);
if (hn) {
struct in_addr **addrtbl = (struct in_addr **)(hn + 1);
UBYTE **alias = (UBYTE **)((UBYTE*)(addrtbl + 2) + sizeof (addr));
UBYTE *name = (UBYTE *)(alias + aliases);
hn->hn_Ent.h_addrtype = AF_INET;
hn->hn_Ent.h_length = sizeof (addr);
hn->hn_Ent.h_addr_list = (char **)addrtbl;
hn->hn_Ent.h_name = name;
hn->hn_Ent.h_aliases = (char **)alias;
/* Make address list */
addrtbl[0] = (struct in_addr *)(addrtbl + 2);
addrtbl[1] = NULL;
bcopy(&addr, addrtbl[0], sizeof (addr));
/* Copy aliases */
aliascpy(hn->hn_Ent.h_name, (UBYTE*)Args[KNDB_DATA],
alias, (UBYTE **)Args[KNDB_ALIAS]);
AddTail((struct List*)&ndb->ndb_Hosts, (struct Node*)hn);
retval = RETURN_OK;
} else {
*errstrp = ERR_MEMORY; retval = RETURN_FAIL;
}
} else {
*errstrp = ERR_VALUE; retval = RETURN_WARN;
}
FreeArgs(rdargs);
} else {
*errstrp = ERR_SYNTAX; retval = RETURN_WARN;
}
return retval;
}
/*
* Parse a net entry.
*/
LONG
addnetent(struct NetDataBase *ndb,
struct RDArgs *rdargs,
UBYTE **errstrp)
{
LONG retval;
LONG Args[NDBARGS] = { 0 };
struct NetentNode *nn;
struct in_addr addr;
int aliases;
if (rdargs = ReadArgs(NETDBTEMPLATE, Args, rdargs)) {
/* convert ip address */
if (inet_aton((char*)Args[KNDB_DATA], &addr)) {
nn = node_alloc(sizeof (*nn),
(UBYTE*)Args[KNDB_NAME],
(UBYTE **)Args[KNDB_ALIAS], &aliases);
if (nn) {
UBYTE **alias = (UBYTE **)(nn + 1);
UBYTE *name = (UBYTE *)(alias + aliases);
nn->nn_Ent.n_addrtype = AF_INET;
nn->nn_Ent.n_name = name;
nn->nn_Ent.n_aliases = (char **)alias;
bcopy(&addr, &nn->nn_Ent.n_net, sizeof (unsigned long));
/* Copy aliases */
aliascpy(nn->nn_Ent.n_name, (UBYTE*)Args[KNDB_NAME],
alias, (UBYTE **)Args[KNDB_ALIAS]);
AddTail((struct List*)&ndb->ndb_Networks, (struct Node*)nn);
retval = RETURN_OK;
} else {
*errstrp = ERR_MEMORY; retval = RETURN_FAIL;
}
} else {
*errstrp = ERR_VALUE; retval = RETURN_WARN;
}
FreeArgs(rdargs);
} else {
*errstrp = ERR_SYNTAX; retval = RETURN_WARN;
}
return retval;
}
/*
* Parse a protocol entry.
*/
LONG
addprotoent(struct NetDataBase *ndb,
struct RDArgs *rdargs,
UBYTE **errstrp)
{
LONG retval;
LONG Args[NDBARGS] = { 0 };
struct ProtoentNode *pn;
int aliases;
if (rdargs = ReadArgs(PROTOCOL_TEMPLATE, Args, rdargs)) {
if (Args[KNDB_DATA]) {
pn = node_alloc(sizeof (*pn), (UBYTE*)Args[KNDB_NAME],
(UBYTE **)Args[KNDB_ALIAS], &aliases);
if (pn) {
UBYTE **alias = (UBYTE **)(pn+1);
UBYTE *name = (UBYTE *)(alias + aliases);
pn->pn_Ent.p_name = name;
pn->pn_Ent.p_aliases = (char **)alias;
pn->pn_Ent.p_proto = *(LONG *)Args[KNDB_DATA];
/* Copy name and aliases */
aliascpy(name, (UBYTE*)Args[KNDB_NAME],
alias, (UBYTE **)Args[KNDB_ALIAS]);
AddTail((struct List*)&ndb->ndb_Protocols, (struct Node*)pn);
retval = RETURN_OK;
} else {
*errstrp = ERR_MEMORY; retval = RETURN_FAIL;
}
} else {
*errstrp = ERR_VALUE; retval = RETURN_WARN;
}
FreeArgs(rdargs);
} else {
*errstrp = ERR_SYNTAX; retval = RETURN_WARN;
}
return retval;
}
/*
* Parse a Name Server entry
*/
LONG
addnameservent(struct NetDataBase *ndb,
struct RDArgs *rdargs,
UBYTE **errstrp)
{
UBYTE Buffer[KEYWORDLEN];
LONG BufLen = sizeof (Buffer);
struct in_addr ns_addr;
struct NameserventNode *nsn;
if (ReadItem(Buffer, BufLen, &rdargs->RDA_Source) <= 0) {
*errstrp = ERR_SYNTAX;
return RETURN_WARN;
}
if (!inet_aton(Buffer, &ns_addr)) {
*errstrp = ERR_VALUE;
return RETURN_WARN;
}
if ((nsn = bsd_malloc(sizeof (*nsn), M_NETDB, M_WAITOK)) == NULL) {
*errstrp = ERR_MEMORY;
return RETURN_FAIL;
}
nsn->nsn_EntSize = sizeof (nsn->nsn_Ent);
nsn->nsn_Ent.ns_addr = ns_addr;
AddTail((struct List*)&ndb->ndb_NameServers, (struct Node*)nsn);
return RETURN_OK;
}
/*
* Parse a Domain Name entry
*/
LONG
adddomainent(struct NetDataBase *ndb,
struct RDArgs *rdargs,
UBYTE **errstrp)
{
UBYTE Buffer[REPLYBUFLEN];
LONG BufLen = sizeof (Buffer);
struct DomainentNode *dn;
short nodesize;
if (ReadItem(Buffer, BufLen, &rdargs->RDA_Source) <= 0) {
*errstrp = ERR_SYNTAX;
return RETURN_WARN;
}
nodesize = sizeof (*dn) + strlen(Buffer) + 1;
if ((dn = bsd_malloc(nodesize, M_NETDB, M_WAITOK)) == NULL) {
*errstrp = ERR_MEMORY;
return RETURN_FAIL;
}
dn->dn_EntSize = nodesize - sizeof (struct GenentNode);
dn->dn_Ent.d_name = (char *)(dn + 1);
strcpy((char *)(dn + 1), Buffer);
AddTail((struct List*)&ndb->ndb_Domains, (struct Node*)dn);
return RETURN_OK;
}
/*
* Parse a access control entry.. after reading the whole netdatabase
* access list must be reorganized;
*/
LONG
addaccessent(struct NetDataBase *ndb,
struct RDArgs *rdargs,
const UBYTE **errstrp)
{
LONG retval = RETURN_WARN;
LONG Args[ACCARGS] = { 0 };
ULONG host, mask;
UWORD port, flags = ACF_CONTINUE;
if (ndb->ndb_AccessCount >= TMPACTSIZE / sizeof (struct AccessItem)) {
*errstrp = "Too many access control items\n";
return retval; /* copy propagation expected */
}
if ((rdargs = ReadArgs(ACCESS_TEMPLATE, Args, rdargs)) != NULL) {
if (strcmp((char *)Args[KACC_PORT], "*") == 0)
port = 0;
else if (strcmp((char *)Args[KACC_PORT], "@") == 0) {
port = 0; flags |= ACF_PRIVONLY;
}
else if (StrToLong((char *)Args[KACC_PORT], (LONG *)&host) > 0
&& host != 0) {
if (host > 0xffff) {
*errstrp = "Illegal port value\n";
goto exit;
}
port = host;
}
else {
struct ServentNode * entNode;
if ((entNode =
findServentNode(ndb, (char *)Args[KACC_PORT], "tcp")) != NULL)
port = entNode->sn_Ent.s_port;
else {
*errstrp = "Illegal port value\n";
goto exit;
}
}
{
int zmask = 0xFFFFFFFF;
int i = 0, ls = 0, dots = 0;
#define hm ((char *)Args[KACC_HOSTMASK])
while ((hm[i] >= '0' && hm[i] <= '9') || hm[i] == '.' || hm[i] == '*') {
if (hm[i] == '.') {
ls = 0;
dots++;
}
else if (hm[i] == '*') {
hm[i] = '0';
ls = 1;
zmask ^= (0xFF000000 >> 8 * dots);
}
i++;
}
if (ls == 1)
while (dots++ < 3)
zmask ^= (0xFF000000 >> 8 * dots);
if (hm[i] == '/') {
hm[i++] = '\0';
if (inet_aton(&hm[i], (struct in_addr *)&mask) == 0) {
*errstrp = "Illegal mask value\n";
goto exit;
}
}
else
mask = 0xffffffff;
mask &= zmask;
if (inet_aton(hm, (struct in_addr *)&host) == 0) {
*errstrp = "Illegal host value\n";
goto exit;
}
#undef hm
}
if (strcmp((char *)Args[KACC_ACCESS], "allow") == 0)
flags |= ACF_ALLOW;
else if (strcmp((char *)Args[KACC_ACCESS], "deny") != 0) {
*errstrp = "Illegal access value\n";
goto exit;
}
if (Args[KACC_LOG])
flags |= ACF_LOG;
ndb->ndb_AccessTable[ndb->ndb_AccessCount].ai_port = port;
ndb->ndb_AccessTable[ndb->ndb_AccessCount].ai_host = host;
ndb->ndb_AccessTable[ndb->ndb_AccessCount].ai_mask = mask;
ndb->ndb_AccessTable[ndb->ndb_AccessCount].ai_flags = flags;
ndb->ndb_AccessCount++;
retval = 0;
exit:
FreeArgs(rdargs);
}
else
*errstrp = ERR_SYNTAX;
return retval;
}
/*
* Add an entry into NetDB.
* Caller must have a write lock on ndb
*/
LONG
addndbent(struct NetDataBase *ndb,
struct RDArgs *rdargs,
UBYTE **errstrp)
{
if (NDB) {
LONG item;
enum ndbtype which;
UBYTE Buffer[KEYWORDLEN];
/* Get entry type */
item = ReadItem(Buffer, sizeof (Buffer), &rdargs->RDA_Source);
if (item == 0)
return RETURN_OK; /* empty line */
if (item < 0) {
*errstrp = ERR_SYNTAX;
return RETURN_WARN;
}
if ((which = FindArg(NETDBENTRY, Buffer)) < 0) {
*errstrp = ERR_UNKNOWN;
return RETURN_WARN;
}
return ndb_parse_funs[which](ndb, rdargs, errstrp);
} else {
*errstrp = ERR_NONETDB;
return RETURN_FAIL;
}
}
/*
* Read in a NetDataBase file
*/
LONG
read_netdb(struct NetDataBase *ndb, UBYTE *fname,
const UBYTE** errstrp, struct CSource *res, int prefixindex)
{
LONG warnval = RETURN_OK;
LONG retval = RETURN_OK, ioerr = 0;
UBYTE *p, *buf = AllocMem(CONFIGLINELEN, MEMF_PUBLIC);
struct RDArgs *rdargs;
BPTR fh;
short line = 0;
ndb_parse_f parser;
BPTR lock, oldcd;
/* Get an exclusive lock on the database.
* Multiple locks are OK (when this function is called recursively)
*/
LOCK_W_NDB(ndb);
if (ndb->ndb_Lock.ss_NestCount > 10) {
UNLOCK_NDB(ndb);
*errstrp = "Too many files included";
return RETURN_ERROR;
}
if (buf) {
/* CD to netdb directory */
lock = Lock(_PATH_DB, ACCESS_READ);
if (lock)
oldcd = CurrentDir(lock);
if (fh = Open(fname, MODE_OLDFILE)) {
if (rdargs = AllocDosObject(DOS_RDARGS, NULL)) {
/* initialize CSource of the rdargs */
rdargs->RDA_Source.CS_Buffer = buf;
/* initialize rest fields (see dos/rdargs.h) */
rdargs->RDA_DAList = NULL;
rdargs->RDA_ExtHelp = NULL;
rdargs->RDA_Flags = 0;
if (prefixindex < 0)
parser = addndbent; /* no prefix */
else
parser = ndb_parse_funs[prefixindex];
while (FGets(fh, buf, CONFIGLINELEN - 1)) {
line++; /* maintain line number */
/* pass by white space */
for (p = buf; *p == ' ' || *p == '\t' || *p == '\r'; p++)
;
rdargs->RDA_Source.CS_CurChr = p - buf;
if (*p == '#' || *p == ';' || *p == '\n') /* only a comment line */
continue;
/* remove comments & calc length */
for (; *p; p++) {
if (*p == '#' || *p == ';') {
*p++ = '\n';
*p = '\0'; /* terminate line */
break;
}
}
/* ensure that line ends with '\n' (ReadArgs() depends on it) */
if (*(p - 1) != '\n') {
*p++ = '\n';
*p = '\0';
}
rdargs->RDA_Source.CS_Length = p - buf;
rdargs->RDA_Buffer = NULL;
rdargs->RDA_BufSiz = 0;
retval = parser(ndb, rdargs, errstrp);
if (retval == RETURN_OK)
continue;
if (retval != RETURN_WARN) /* severe error */
break;
/* Log the error */
log(LOG_NOTICE, "NetDB(%s) line %ld: %s before col %ld\n",
fname, line, *errstrp, rdargs->RDA_Source.CS_CurChr);
warnval = retval;
}
/* Check file error */
ioerr = IoErr();
FreeDosObject(DOS_RDARGS, rdargs);
}
Close(fh);
} else {
ioerr = IoErr();
}
if (ioerr) {
Fault(ioerr, "readnetdb", res->CS_Buffer, res->CS_Length);
*errstrp = res->CS_Buffer;
retval = RETURN_ERROR;
}
/* return old current directory */
if (lock) {
CurrentDir(oldcd);
UnLock(lock);
}
FreeMem(buf, CONFIGLINELEN);
} else {
*errstrp = ERR_MEMORY;
retval = RETURN_FAIL;
}
UNLOCK_NDB(ndb);
return retval > warnval? retval: warnval;
}
/*
* Parse the 'ADD' command
*/
LONG
do_netdb(struct CSource *csarg, UBYTE **errstrp, struct CSource *res)
{
struct RDArgs *rdargs;
LONG retval;
if (rdargs = AllocDosObject(DOS_RDARGS, NULL)) {
/* initialize CSource of the rdargs */
rdargs->RDA_Source = *csarg;
/* initialize rest fields (see <dos/rdargs.h>) */
rdargs->RDA_DAList = NULL;
rdargs->RDA_Buffer = NULL;
rdargs->RDA_BufSiz = 0;
rdargs->RDA_ExtHelp = NULL;
rdargs->RDA_Flags = 0;
LOCK_W_NDB(NDB);
retval = addndbent(NDB, rdargs, errstrp);
UNLOCK_NDB(NDB);
FreeDosObject(DOS_RDARGS, rdargs);
}
else
retval = RETURN_FAIL;
return retval;
}
/*
* Initialize the Network Data Base
*/
LONG
init_netdb(void)
{
UBYTE result[REPLYBUFLEN + 1]; /* for error returns */
struct CSource res;
UBYTE *errstr;
LONG retval;
res.CS_Buffer = result;
res.CS_Length = sizeof (result);
res.CS_CurChr = 0;
/* Allocate the NetDataBase */
if (!(NDB = alloc_netdb(NULL))) {
return RETURN_FAIL;
}
/* Read in the default data base file */
retval = read_netdb(NDB, netdbname, &errstr, &res, -1);
if (retval)
log(LOG_WARNING, "init_netdb: file %s: %s", netdbname, errstr);
else
setup_accesscontroltable(NDB);
return retval;
}
void netdb_deinit(void)
{
/* A Placeholder for possible future deinitializations */
}
/*
* Reset the NetDataBase
*/
LONG reset_netdb(struct CSource *cs,
UBYTE **errstrp,
struct CSource *res)
{
LONG retval;
struct NetDataBase *newnetdb;
/* Allocate a temporary NetDataBase */
if (!(newnetdb = alloc_netdb(NULL))) {
*errstrp = ERR_MEMORY;
return RETURN_FAIL;
}
retval = read_netdb(newnetdb, netdbname, errstrp, res, -1);
if (retval == RETURN_OK) {
/*
* Success
*/
struct MinList *gl, *ol;
setup_accesscontroltable(NDB);
/* Now clear the old lists of the NDB */
LOCK_W_NDB(NDB);
free_netdb(NDB);
/*
* Transfer the lists of the new (temporary) database
* to the NDB.
*/
for (gl = (struct MinList *)&newnetdb->ndb_Hosts,
ol = (struct MinList *)&NDB->ndb_Hosts;
gl <= (struct MinList *)&newnetdb->ndb_Domains;
gl++, ol++) {
if (gl->mlh_Head->mln_Succ) {
/* There is a non-empty list */
*ol = *gl;
ol->mlh_Head->mln_Pred = (struct MinNode*)&ol->mlh_Head;
ol->mlh_TailPred->mln_Succ = (struct MinNode*)&ol->mlh_Tail;
}
}
NDB->ndb_AccessTable = newnetdb->ndb_AccessTable;
/*
* Perhaps ugly...
*/
newnetdb->ndb_AccessTable = NULL;
UNLOCK_NDB(NDB);
} else {
free_netdb(newnetdb);
}
bsd_free(newnetdb, M_NETDB); /* free the temporary database */
return retval;
}